package com.atguigu.spzx.order.service.impl;

import com.atguigu.spzx.feign.cart.CartFeignClient;
import com.atguigu.spzx.feign.product.ProductFeignClient;
import com.atguigu.spzx.feign.user.UserFeignClient;
import com.atguigu.spzx.model.dto.h5.OrderInfoDto;
import com.atguigu.spzx.model.entity.h5.CartInfo;
import com.atguigu.spzx.model.entity.order.OrderInfo;
import com.atguigu.spzx.model.entity.order.OrderItem;
import com.atguigu.spzx.model.entity.order.OrderLog;
import com.atguigu.spzx.model.entity.product.ProductSku;
import com.atguigu.spzx.model.entity.user.UserAddress;
import com.atguigu.spzx.model.entity.user.UserInfo;
import com.atguigu.spzx.model.vo.common.ResultCodeEnum;
import com.atguigu.spzx.model.vo.h5.TradeVo;
import com.atguigu.spzx.order.enums.OperatorType;
import com.atguigu.spzx.order.enums.OrderType;
import com.atguigu.spzx.order.mapper.OrderInfoMapper;
import com.atguigu.spzx.order.mapper.OrderItemMapper;
import com.atguigu.spzx.order.mapper.OrderLogMapper;
import com.atguigu.spzx.order.service.OrderService;
import com.atguigu.spzx.service.exception.GuliException;
import com.atguigu.spzx.service.utils.AuthContextUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import jakarta.annotation.Resource;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * ClassName: OrderServiceImpl
 * Package: com.atguigu.spzx.order.service.impl
 * Description:
 *
 * @Author 刘强
 * @Create 2024/7/17 17:30
 * @Version 1.0
 */
@Service
public class OrderServiceImpl implements OrderService {
    @Resource
    private CartFeignClient cartFeignClient;
    @Resource
    private ProductFeignClient productFeignClient;
    @Resource
    private UserFeignClient userFeignClient;
    @Resource
    private OrderInfoMapper orderInfoMapper;
    @Resource
    private OrderItemMapper orderItemMapper;
    @Resource
    private OrderLogMapper orderLogMapper;

    /**
     * 获取订单项列表和总金额  -> 订单项来自于用户选中的购物车项  -> 购物车服务
     *
     * @return
     */
    @Override
    public TradeVo trade() {
        // 1. 获取选中的购物车项列表 -> 购物车服务  -> 远程访问 -> openFeign
        //    注意：这里需要把token带过去，但是openFeign客户端默认会导致请求头丢失 -> 因为创建了一个新的http客户端，没有原来的请求报文了
        List<CartInfo> cartInfoList = cartFeignClient.getAllCkecked();
        BigDecimal totalAmount = new BigDecimal(0);
        List<OrderItem> orderItemList = cartInfoList.stream().map(cartInfo -> {
            OrderItem orderItem = new OrderItem();
            orderItem.setSkuId(cartInfo.getSkuId());
            orderItem.setSkuName(cartInfo.getSkuName());
            orderItem.setSkuNum(cartInfo.getSkuNum());
            orderItem.setSkuPrice(cartInfo.getCurrentPrice());
            orderItem.setThumbImg(cartInfo.getImgUrl());
            return orderItem;
        }).collect(Collectors.toList());
        for (OrderItem orderItem : orderItemList) {
            BigDecimal skuNum = new BigDecimal(orderItem.getSkuNum().intValue());
            totalAmount = (totalAmount.add(orderItem.getSkuPrice())).multiply(skuNum);
        }
        TradeVo tradeVo = new TradeVo();
        tradeVo.setOrderItemList(orderItemList);
        tradeVo.setTotalAmount(totalAmount);
        return tradeVo;
    }

    /**
     * 保存订单
     *
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long submitOrder(OrderInfoDto orderInfoDto) {
        // 0.
        UserInfo userInfo = AuthContextUtils.get();
        // 1. 校验库存，库存锁定(暂时不做)  -> 库存服务
        List<OrderItem> orderItemList = orderInfoDto.getOrderItemList();
        if (CollectionUtils.isEmpty(orderItemList)) {
            throw new GuliException(ResultCodeEnum.DATA_ERROR);
        }
        for (OrderItem orderItem : orderItemList) {
            ProductSku productSku = productFeignClient.getBySkuId(orderItem.getSkuId());
            if (orderItem.getSkuNum() > productSku.getStockNum()) {
                throw new GuliException(ResultCodeEnum.STOCK_LESS);
            }
            // 从后端拉取真实价格
            orderItem.setSkuPrice(productSku.getSalePrice());
        }
        // 2. 保存订单 -> 收货人地址信息 -> 收货人地址id -> 用户服务
        // 计算总金额
        BigDecimal totalAmount = getTotalAmount(orderItemList);
        // 获取收货人的地址信息 ->  用户服务
        UserAddress userAddress = userFeignClient.getUserAddressById(orderInfoDto.getUserAddressId());
        // 创建订单对象，并且赋值
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setUserId(userInfo.getId());
        orderInfo.setNickName(userInfo.getNickName());
        orderInfo.setOrderNo(System.currentTimeMillis() + UUID.randomUUID().toString().replaceAll("-", ""));
        orderInfo.setTotalAmount(totalAmount);
        orderInfo.setCouponAmount(new BigDecimal(0));
        orderInfo.setOriginalTotalAmount(totalAmount);
        orderInfo.setFeightFee(new BigDecimal(0)); // orderInfo.getFeightFee() -> 当前项目没有运费计算接口
        orderInfo.setPayType(2);
        orderInfo.setOrderStatus(OrderType.WAIT_PAY.getValue()); // 代付款
        orderInfo.setReceiverName(userAddress.getName());
        orderInfo.setReceiverPhone(userAddress.getPhone());
        orderInfo.setReceiverTagName(userAddress.getTagName());
        orderInfo.setReceiverProvince(userAddress.getProvinceCode());
        orderInfo.setReceiverCity(userAddress.getCityCode());
        orderInfo.setReceiverDistrict(userAddress.getDistrictCode());
        orderInfo.setReceiverAddress(userAddress.getFullAddress());
        orderInfo.setRemark("提交订单");
        orderInfo.setCreateTime(new Date());
        orderInfo.setUpdateTime(new Date());
        orderInfoMapper.save(orderInfo);
        // 3. 保存订单项
        for (OrderItem orderItem : orderItemList) {
            orderItem.setOrderId(orderInfo.getId());
            orderItem.setUpdateTime(new Date());
            orderItem.setCreateTime(new Date());
        }
        orderItemMapper.saveBatch(orderItemList);
        // 4. 保存订单日志
        OrderLog orderLog = new OrderLog();
        orderLog.setOrderId(orderInfo.getId());
        orderLog.setOperateUser(OperatorType.MOBILE.name());
        orderLog.setProcessStatus(orderInfo.getOrderStatus());
        orderLog.setNote("用户提交订单;无优惠券");
        orderLog.setCreateTime(new Date());
        orderLog.setUpdateTime(new Date());
        orderLogMapper.save(orderLog);
        // 5. 清空选中的购物车项
        cartFeignClient.clearChecked();
        return orderInfo.getId();
    }

    /**
     * 根据订单id获取订单信息
     *
     * @param orderId
     * @return
     */
    @Override
    public OrderInfo getById(Long orderId) {
        OrderInfo orderInfo = orderInfoMapper.getById(orderId);
        return orderInfo;
    }

    /**
     * 立即购买 --> 订单确认页面 -> 用户的地址列表(发送到另一个服务的请求) ; 订单项信息-> 商品sku
     *
     * @param skuId
     * @return
     */
    @Override
    public TradeVo buy(Long skuId) {
        ProductSku productSku = productFeignClient.getBySkuId(skuId);
        ArrayList<OrderItem> orderItemList = new ArrayList<>();
        OrderItem orderItem = new OrderItem();
        orderItem.setSkuId(productSku.getId());
        orderItem.setSkuName(productSku.getSkuName());
        orderItem.setThumbImg(productSku.getThumbImg());
        orderItem.setSkuPrice(productSku.getSalePrice());
        if (productSku.getStockNum() < 1) {
            throw new GuliException(ResultCodeEnum.STOCK_LESS);
        }
        orderItem.setSkuNum(1);
        orderItemList.add(orderItem);
        TradeVo tradeVo = new TradeVo();
        tradeVo.setTotalAmount(productSku.getSalePrice());
        tradeVo.setOrderItemList(orderItemList);
        return tradeVo;
    }

    /**
     * 分页带条件(订单状态)查询订单列表
     *
     * @param pageNum
     * @param pageSize
     * @param orderStatus
     * @return
     */
    @Override
    public PageInfo<OrderInfo> findByPage(Integer pageNum, Integer pageSize, Integer orderStatus) {
        Long userId = AuthContextUtils.get().getId();
        PageHelper.startPage(pageNum, pageSize);
        List<OrderInfo> orderInfoList = orderInfoMapper.findByStatusAndUserId(orderStatus, userId);
        return new PageInfo<>(orderInfoList);
    }

    /**
     * 根据订单编号查询订单信息
     * @param orderNo
     * @return
     */
    @Override
    public OrderInfo getByOrderNo(String orderNo) {
        return orderInfoMapper.findByOrderNo(orderNo);
    }

    /**
     * 更新订单状态
     * @param orderStatus
     */
    @Override
    public void updateOrderStatus(Integer orderStatus) {
        orderInfoMapper.updateOrderStatus(orderStatus);
    }

    /**
     * 保存订单日志
     * @param orderId
     * @param processStatus
     */
    @Override
    public void saveOrderLog(Long orderId, Integer processStatus) {
        OrderLog orderLog = new OrderLog();
        orderLog.setOrderId(orderId);
        orderLog.setOperateUser("用户");
        orderLog.setProcessStatus(processStatus);
        String note = getNoteByProcessStatus(processStatus);
        orderLog.setNote(note);
        orderLog.setCreateTime(new Date());
        orderLog.setUpdateTime(new Date());
        orderLogMapper.save(orderLog);
    }

    @NotNull
    private static String getNoteByProcessStatus(Integer processStatus) {
        String note = "";
        if(processStatus == 0){
            note = "待付款";
        }else if(processStatus == 1){
            note = "已支付";
        }else {
            throw new GuliException(ResultCodeEnum.DATA_ERROR);
        }
        return note;
    }

    /**
     * 获取总金额
     *
     * @param orderItemList
     * @return
     */
    private BigDecimal getTotalAmount(List<OrderItem> orderItemList) {
        BigDecimal totalAmount = new BigDecimal(0);
        if (CollectionUtils.isEmpty(orderItemList)) {
            return totalAmount;
        }
        for (OrderItem orderItem : orderItemList) {
            totalAmount = totalAmount.add(orderItem.getSkuPrice().multiply(new BigDecimal(orderItem.getSkuNum())));
        }
        return totalAmount;
    }
}
